package cn.fan.vertd;

import cn.fan.vertd.utils.RedisUtil;
import io.vertx.config.ConfigRetriever;
import io.vertx.config.ConfigRetrieverOptions;
import io.vertx.config.ConfigStoreOptions;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.redis.client.Command;
import io.vertx.redis.client.RedisConnection;
import io.vertx.redis.client.Request;
import io.vertx.redis.client.Response;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.concurrent.TimeUnit;

public class MainVerticle extends AbstractVerticle {

    private static final Logger log = LogManager.getLogger();

    @Override
    public void start(Promise<Void> startPromise) throws Exception {
        loadConfig().onSuccess(config -> {
            JsonArray verticleNames = config.getJsonArray("deployVerticals");
            String packageName = this.getClass().getPackageName();
            for (Object verticleName : verticleNames) {
                String fullName = packageName + ".verticle." + verticleName;
                vertx.deployVerticle(fullName, new DeploymentOptions()
                        .setConfig(config))
                        .onSuccess(event -> {
                            log.info("{} has deployed, deployID is {}", verticleName, event);
                        });
            }
        }).onFailure(event -> {
            log.error("Failed to load configuration");
        });

        Router router = Router.router(vertx);
        router.get("/api/v1/hello").handler(this::helloHandle);
        router.get("/api/v1/context").handler(this::contextHandle);
        vertx.createHttpServer()
                .requestHandler(router)
                .listen(8080);
    }

    @Override
    public void stop(Promise<Void> stopPromise) throws Exception {
        super.stop(stopPromise);
    }

    private void helloHandle(RoutingContext ctx) {
        vertx.executeBlocking(future -> {
            try {
                TimeUnit.SECONDS.sleep(10);
                System.out.println("sleep......");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, res -> {
            System.out.println("res: " + res);
        });
        RedisConnection conn = RedisUtil.getRedisConnection();
        conn.send(Request.cmd(Command.HSET).arg("userSet").arg("userId").arg(ctx.request().getParam("userId")));
        System.out.println("request param: " + ctx.request().getParam("userId"));
        ctx.response().setStatusCode(200)
                .setStatusMessage("OK")
                .putHeader("Content-Type","text/plain")
                .end("hello world");
    }

    private void contextHandle(RoutingContext ctx) {
        RedisConnection conn = RedisUtil.getRedisConnection();
        Future<Response> responseFuture = conn.send(Request.cmd(Command.HGET).arg("userSet").arg("userId"));
        responseFuture.onSuccess(result -> {
            log.info("result: {}", result);
            ctx.response().setStatusCode(200)
                    .setStatusMessage("OK")
                    .putHeader("Content-Type","text/plain")
                    .end(result.toString());
        }).onFailure(event -> {
            log.error("get failed: ", event);
            ctx.response().setStatusCode(500)
                    .setStatusMessage("ERROR")
                    .putHeader("Content-Type","text/plain")
                    .end("this is a error");
        });

    }

    private Future<JsonObject> loadConfig() {
        ConfigStoreOptions fileStore = new ConfigStoreOptions()
                .setType("file")
                .setConfig(new JsonObject().put("path", "config.json"));
        ConfigRetrieverOptions options = new ConfigRetrieverOptions();
        options.addStore(fileStore);

        ConfigRetriever retriever = ConfigRetriever.create(vertx, options);
        return retriever.getConfig();
    }

}
